﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;

namespace InfFront.UICore
{
    public class FieldDataPacker
    {
        #region Private variables
        private List<IDataTypeTraits> traits = null;
        #endregion

        public FieldDataPacker(IEnumerable<IDataType> fieldTypes)
        {
            this.traits = new List<IDataTypeTraits>();
            foreach (var desc in fieldTypes)
            {
                this.traits.Add(desc.GetTraits());
            }
        }

        public FieldDataPacker(IEnumerable<IDataTypeTraits> fieldTypeTraits)
        {
            this.traits = new List<IDataTypeTraits>(fieldTypeTraits);
        }

        public FieldDataPacker(IDataType fieldType)
        {
            this.traits = new List<IDataTypeTraits>();
            this.traits.Add(fieldType.GetTraits());
        }

        public FieldDataPacker(IDataTypeTraits fieldTypeTraits)
        {
            this.traits = new List<IDataTypeTraits>();
            this.traits.Add(fieldTypeTraits);
        }

        public void Pack(BinaryWriter stream, IEnumerator<object> fieldValues)
        {
            for (int i = 0; i < traits.Count && fieldValues.MoveNext(); ++i)
            {
                traits[i].WriteData(fieldValues.Current, stream); 
            }
        }

        public void PackFirst(BinaryWriter stream, object fieldValue)
        {
            traits[0].WriteData(fieldValue, stream);
        }

        public void Pack(Stream stream, IEnumerator<object> fieldValues)
        {
            Pack(new BinaryWriter(stream), fieldValues);
        }

        public void PackFirst(Stream stream, object fieldValue)
        {
            PackFirst(new BinaryWriter(stream), fieldValue);
        }
    }

    public class FieldDataUnpacker
    {
        #region Private variables
        private List<IDataTypeTraits> traits = null;
        #endregion

        public FieldDataUnpacker(IEnumerable<IDataType> fieldTypes)
        {
            this.traits = new List<IDataTypeTraits>();
            foreach (var desc in fieldTypes)
            {
                this.traits.Add(desc.GetTraits());
            }
        }

        public FieldDataUnpacker(IEnumerable<IDataTypeTraits> fieldTypeTraits)
        {
            this.traits = new List<IDataTypeTraits>(fieldTypeTraits);
        }

        public FieldDataUnpacker(IDataType fieldType)
        {
            this.traits = new List<IDataTypeTraits>();
            this.traits.Add(fieldType.GetTraits());
        }

        public FieldDataUnpacker(IDataTypeTraits fieldTypeTraits)
        {
            this.traits = new List<IDataTypeTraits>();
            this.traits.Add(fieldTypeTraits);
        }

        private IEnumerator<object> DoUnpack(BinaryReader data)
        {
            foreach (var t in traits)
                yield return t.ReadData(data);
        }

        public IEnumerator<object> Unpack(BinaryReader data)
        {
            if (data.BaseStream.Position == data.BaseStream.Length)
                return null;
            return DoUnpack(data);
        }

        public object UnpackFirst(BinaryReader data)
        {
            return traits[0].ReadData(data);
        }

        public IEnumerator<object> Unpack(Stream data)
        {
            return Unpack(new BinaryReader(data));
        }

        public object UnpackFirst(Stream data)
        {
            return UnpackFirst(new BinaryReader(data));
        }

    }
}